import json
import os
from typing import Dict, List

from aiogram.types import BotCommand

from factories import generate_inline_keyboard
from mytypes import (CB_button, CB_buy_pro, CB_screen, CB_video,
                         JSON_Button, JSON_MenuItem, JSON_VideoItem, KB_Item,
                         Screen)
from utils import debugger

_screens: Dict[str, Screen] = dict()


def _add_screen(item: JSON_MenuItem, path: str, parent: str = None):
    """Add new screen to Dict"""
    menuItems: List[KB_Item] = []
    content = f"<b>{item.name}</b>\n{item.text}"

    if len(item.children) > 0:
        index = 0
        for child in item.children:
            child = JSON_MenuItem(**child)
            _add_screen(item=child, path=f"{path}/{index}", parent=path)
            content = f"{content}\n\n<b>{child.name}</b> - {child.short}"
            menuItems.append(
                KB_Item(text=child.name, cb_data=CB_screen(path=f"{path}/{index}"))
            )
            index += 1

    if len(item.videos) > 0:
        index = 0
        for video in item.videos:
            # serialize row
            video = JSON_VideoItem(**video)
            # generate screen
            _screens[f"{path}/{index}"] = Screen(
                video_id=video.id, vide_title=video.title
            )
            menuItems.append(
                KB_Item(text=video.title, cb_data=CB_video(path=f"{path}/{index}"))
            )
            index += 1

    if len(item.buttons) > 0:
        index = 0
        for btn in item.buttons:
            # serialize row
            print(btn)
            btn = JSON_Button(**btn)            
            menuItems.append(KB_Item(text=btn.title, cb_data=CB_button(path=btn.data)))
            index += 1

    # make BACK button
    if parent:
        menuItems.append(KB_Item(text="<< НАЗАД", cb_data=CB_screen(path=parent)))

    # save screen
    _screens[path] = Screen(
        content=content, keyboard=generate_inline_keyboard(items=menuItems)
    )


bot_commands = [BotCommand(command="info", description="Справочный экран")]


def generate_screens():
    """Parse JSON and generate all screens"""

    debugger.info(f"Screens generation.")

    __location__ = os.path.realpath(
        os.path.join(os.getcwd(), os.path.dirname(__file__))
    )

    filename = os.path.join(__location__, "..", "content", "full_menu.json")

    debugger.info(f"Parse {filename}.")

    with open(filename) as f:
        # JSON parse
        json_data = json.load(f)
        content = f"<b>Список доступных команд</b>"
        for key, row in json_data.items():
            # serialize row
            item = JSON_MenuItem(**row)
            # generate screen
            _add_screen(item=item, path=key)
            # fill content
            content = f"{content}\n\n<b>/{key}</b> - {item.short}"
            bot_commands.append(BotCommand(command=key, description=item.name))

    # generate HELLO screen
    _screens["root"] = Screen(content)
    debugger.info(f"Generated {len(_screens)} screens.")


def get_screen(path: str) -> Screen:
    """Get screen by path"""
    debugger.info(f"Get screen: {path}.")
    return _screens.get(path)


def get_ProScreen(user_id: str) -> Screen:
    """Get screen by path"""
    return Screen(
        content="\n".join(
            [
                "К сожалению видео-материалы доступны только при офрмлении PRO доступа.",
                "Вы можете купить PRO доступ за 990 ₽ единоразово.",
                "Жми на кнопку и оплачивай!",
            ]
        ),
        keyboard=generate_inline_keyboard(
            [KB_Item(text="Купить PRO (990 ₽)", cb_data=CB_buy_pro(user_id=user_id))]
        ),
    )
